xxxxxxxxxxmodule teapo.files { export class FileTree { private _ul: HTMLUListElement; private _rootNode: Node[];​ access: SyncStorageAccess;​ constructor(private _host: HTMLUListElement) { this._ul = getChildUL(this._host); // TODO: do something if ul is null​ this.access = { update: (byFullPath, timestamp) => this._update, read: (fullPaths) => this._read(fullPaths) }; }​ private _update( byFullPath: storage.PropertiesByFullPath, timestamp: number): void { }​ private _read( fullPaths: string[]): storage.PropertiesByFullPath { return {}; }​ } class Node { name: string; fullPath: string;​ private _resolvedUL = false; private _ul: HTMLUListElement; private _children: Node[]; private _li: HTMLLIElement;​ constructor( parentPath: string, li: HTMLLIElement); constructor(ul: HTMLUListElement); constructor (arg1, arg2) { if (arg2) {​ this._li = li; var liText = getLIText(this._li); var slashPos = liText.indexOf('/'); if (slashPos >= 0) this._handleComplexPathOnLoad(liText); this.name = liText; this.fullPath = parentPath + '/' + liText; this._ul = null; this._children = null; } else {​ this.name = ''; this.fullPath = ''; this._ul = ul; this._li = null; } }​ getNode(path: string, createIfAbsent: boolean): Node {​ this._ensureULResolved();​ if (!this._ul) throw new Error('Node is not a directory.'); var name: string, restPath: string; var slashPos = path.indexOf('/'); while (!slashPos) { // slight normalization, keep it for the sake of root paths path = path.slice(1); slashPos = path.indexOf('/'); }​ if (slashPos < 0) {